package com.smart.redis.transaction;

import java.io.IOException;
import java.util.List;

import com.smart.redis.client.RedisClient;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

/**
 * 
* @ClassName: Redis2Transaction 
* @Description: TODO redis 事务 
* @Company:e-smart.top
* @author Thinkpad 
* @version 1.0 2018年8月31日 上午10:55:21
 */
public class Redis2Transaction {

	public static void main(String[] args) {
		Jedis jedis = RedisClient.getJedis();
		/**
		 * WATCH命令可以监控一个或多个键，一旦其中有一个键被修改（或删除），
		 * 之后的事务就不会执行。监控一直持续到EXEC命令（事务中的命令是在EXEC之后才执行的，
		 * 所以在MULTI命令后可以修改WATCH监控的键值）。
		 * 
		 * 在Redis的事务中，WATCH命令可用于提供CAS(check-and-set)功能，且是基于乐观锁的思想。
		 * 假设我们通过WATCH命令在事务执行之前监控了多个Keys，倘若在WATCH之后有任何Key的值发生了变化，
		 * EXEC命令执行的事务都将被放弃，同时返回Null multi-bulk应答以通知调用者事务执行失败。
		 * redis 事务命令主要包括：
		 * 	multi-标记一个事务块的开始
		 * 	exec-执行所有事务块中的命令
		 * 	discard-取消事务，放弃执行事务块中的命令
		 * 	watch-监控一个或者多个key，如果在事务执行之前这个(或这些) key 被其他命令所改动，那么事务将被打断
		 * 	unwatch-取消 WATCH 命令对所有 key 的监视
		 * 
		 * unwatch命令小贴士：
		 * 		如果在执行 WATCH 命令之后， EXEC 命令或 DISCARD 命令先被执行了的话，那么就不需要再执行 UNWATCH 了。
		 * 		因为 EXEC 命令会执行事务，因此 WATCH 命令的效果已经产生了；
		 * 		而 DISCARD 命令在取消事务的同时也会取消所有对 key 的监视，因此这两个命令执行之后，就没有必要执行 UNWATCH 了。
		 * 
		 */
		/**************************场景一：开启事务，并执行命令*****************************************/
		//获取事务
		Transaction multi = jedis.multi();
		//事务块开始
		multi.setnx("wwwww", "11111122222");
		multi.set("zzzz", "11111112222");
		
		//执行事务块中的命令-等同于unwatch命令
		List<Object> exec = multi.exec();
		//命令的返回值集合
		System.out.println(exec.toString());
//		RedisClient.returnToPool(jedis);
		
		/**************************场景二：乐观锁 watch*****************************************/
		
		jedis.watch("wwwww");
		//这里开启之后，会导致下面事务exec执行会被放弃
		jedis.set("wwwww", "11111122222");
		//获取事务
		Transaction multi1 = jedis.multi();
		//事务块开始
		multi.setnx("wwwww", "11111122222");
		multi.set("zzzz", "11111112222");
		//执行代码块中的命令
		List<Object> exec1 = multi1.exec();
		//命令的返回值集合
		System.out.println(exec1.toString());
//		jedis.unwatch();
		
		RedisClient.returnToPool(jedis);
		
	}
}
